#include "syntax.h"

/*Simple affichage*/
void print(char buffer[512])
{
	/*Affichage dans la console et dans le fichier lst*/
	fputs(buffer, lst);
	printf("%s", buffer);
}

/*Affichage de la table des symboles*/
void printSymbole(struct liste *list)
{
	if(list!=NULL)
	{
		struct symbole *courant=list->tete;
		char data[200], TypeI[128], TypeL[128], localisation[128];
		print("\n");

		while(courant!=NULL)
		{
			affichageTypeIdentificateur(courant->typeIdentificateur, TypeI);
			affichageTypeLiteral(courant->typeLiteral, TypeL);
			afficherLocalisation(courant->emplacement, localisation);

			sprintf(data, "Nom=%s; TypeId=%s; TypeVal=%s; Valeur=%s; Dimension=%d; Emplacement=%s; NomEmplacement=%s; Deplacement=%d; nParam=%d; Passage=%d; PtrPile=%d; \n", courant->nom, TypeI, TypeL, courant->valeur, courant->dimension, localisation, courant->nomEmplacement, courant->deplacement, courant->nParam, courant->passage, courant->ptrPile);
	
			print(data);
			courant=courant->suivant;
		}
	}
}

/*Affichage de la pile dans le fichier lst et sur la console*/
void printPile(struct pile *p)
{
	printf("Info pile:\nTaille=%d\nCapacite max=%d\n\n", p->deplacement, p->capaciteMax);

	if(pCompilation->deplacement>0)
	{
		int i;
		char buffer[512];

		for(i=0; i<pCompilation->deplacement; ++i)
		{
			char typeI[128], typeL[128];
			affichageTypeIdentificateur(pCompilation->base[i]->typeIdentificateur, typeI);
			affichageTypeLiteral(pCompilation->base[i]->typeLiteral, typeL);

			sprintf(buffer, "Indice=%d; Nom=%s; TypeId=%s; TypeVal=%s; Valeur=%s; Localisation=%s;\n", i, pCompilation->base[i]->nom, typeI, typeL, pCompilation->base[i]->valeur, pCompilation->base[i]->localisation); 
			fputs(buffer, lst);
			printf("%s", buffer);
		}
	}
}

/*write() writeln read() perso*/
int inputOutput(char nomEmplacement[128], int type)
{
	/*Les déclarations*/
	int stop=1, emplacement, typeI, typeL, negatif, res, flag=0;
	char val[256], varName[128];

	/*Sommes-nous dans une fonction? procédure ou dans le programme main?*/
	if(in_function==1) emplacement=local_fonction;
        else if(in_procedure==1) emplacement=local_procedure;
        else emplacement=global;

	if(type==1 || type==2)
        {
		while(stop==1) //Liste des paramètres
		{
			//Chaque paramètre peut être une expression
			expression(nomEmplacement);
			OUT();	// p_code out
			
			if(strcmp(u_lex, ")")==1 && strcmp(u_lex, ",")==1) token=yylex();
		
			if(strcmp(u_lex, ",")==0); //On continu
			else stop=0; //On arrête
		}
	}
	else /*Read*/
	{
		token=yylex(); 

		while(stop==1) //Liste des paramètres
		{
		        if(token==IDENTIFICATEUR)
		        {
		                
		                //Recherche le symbole, si il existe, on l'empile sinon erreur
		                struct symbole *s=chercherUnSymbole(tableSymbole, u_lex, emplacement, nomEmplacement);
		                if(s==NULL) return ER_ID_PAS_DECLARE;
		                INP(s->typeLiteral, nomEmplacement);

				if(s->typeIdentificateur==cst_entier || s->typeIdentificateur==cst_reel || s->typeIdentificateur==cst_char || s->typeIdentificateur==cst_byte || s->typeIdentificateur==cst_string || s->typeIdentificateur==cst_boolean) 	return ER_AFFECTATION_STO;

				res=STO(s->nom, nomEmplacement, s->deplacement, t_string, var_string);
		        }
			else return ER_TYPE;

			token=yylex(); 

			if(strcmp(u_lex, ",")==0) token=yylex(); //On continu
			else stop=0; //On arrête
		}
	}
	
	//writeln
	if(type==2)	
	{
		res=LIT("\\n", cst_char, t_char, nomEmplacement);
		if(res!=0) return res;

		OUT(t_char);
	}

	return 0;
}


int condition(char nomEmplacement[128])
{
	/*
		Condition= expression+operateur logique+expression
	*/

	/*Déclaration*/
	char operation[5], space[128], buffer[128];
	int i, res, depth=0;

	/*Appel de terme()*/
	depth=terme_expression_counter; terme_expression_counter++;
	strcpy(space, ""); for(i=0; i<depth; ++i) strcat(space, "  ");

	res=expression(nomEmplacement); 
	if(res!=0) return res; 
	
	if(jumpInExp==1)
	{
		token=yylex(); 
		jumpInExp=0;
	}

	if(token!=OPER_LOGIQUE) return ER_COND;
	strcpy(operation, u_lex); 

	res=expression(nomEmplacement);
	if(res!=0) return res;

	/*Appel.txt et syntex.postfix*/
	sprintf(buffer, "%s condition() %s\n", space, operation); fputs(buffer, appel); 
	fputs(operation, postFix); 
	/*Fin*/

	/*Génération p_code*/
	res=OPR(operation);	 
	if(res!=0) return res;
	/*Fin génération*/

	return 0;
}

int terme(char nomEmplacement[128])
{
	/*Déclarations*/
	int i, res, stop=1, depth=0, flagPostFix=0, emplacement, trouve, typeI, typeL, negatif=0;
	char buffer[124], space[124];
	char opPostFix[56], varPostFix[56], val[56], varName[128];

	/*Sommes-nous dans une fonction? procédure ou dans le programme global?*/
	if(in_function==1) emplacement=local_fonction;
        else if(in_procedure==1) emplacement=local_procedure;
        else emplacement=global;

	/*Appel de terme()*/
	depth=terme_expression_counter; terme_expression_counter++;
	strcpy(space, ""); for(i=0; i<depth; ++i) strcat(space, "  "); sprintf(buffer, "%s Dterme()\n", space); fputs(buffer, appel);

	/*Test si la précédente lecture (expression()) est un + ou un -*/
	if(token==OPER_ARITHMETIQUE && (strcmp(u_lex, "+")==0 || strcmp(u_lex, "-")==0))
	{
		if(strcmp(u_lex, "-")==0)
			negatif=1;

		//Si c'est le cas, on lis la suivante
		token=yylex();
	}
	
	strcpy(varName, u_lex); //Copie le nom de la fonction

	/*Début de l'automate*/
	for(;;)
	{
		if(token==SEPARATEUR && strcmp(u_lex, "(")==0) //Reconnaissance de ( expression )
		{
			sprintf(buffer, "%s terme() %s\n", space, u_lex); fputs(buffer, appel); 
			res=expression(nomEmplacement);
			if(res!=0) return res;

			if(token!=SEPARATEUR || strcmp(u_lex, ")")==1) return ER_PARENTHESE_FERMANTE;
		}
		else if(token==IDENTIFICATEUR || token==CONST_ENTIERE || token==CONST_REELLE || CONST_BOOLEENNE || token==CONST_CHAINE || token==CONST_CARACTERE) //Reconnaissance d'un identificateur, d'un entier ou d'un reel
		{
			strcpy(varPostFix, u_lex);

			/*Test si il est déclaré*/
			if(token==IDENTIFICATEUR)
			{
				//Recherche le symbole, si il existe, on l'empile sinon erreur
		
				struct symbole *select=chercherUnSymbole(tableSymbole, u_lex, emplacement, nomEmplacement);
				int execute_function=0, trouve=0;
				if(select==NULL)
				{	/*Cherche dans la partie fonction*/
					select=chercherUnSymbole(tableSymbole, u_lex, local_fonction, u_lex);
					if(select==NULL)
					{	/*Cherche dans la partie procédure*/
						select=chercherUnSymbole(tableSymbole, u_lex, local_procedure, u_lex);
						if(select!=NULL) return ER_EXEC_PROCEDURE;	
					}
					else{ trouve=1; execute_function=1; }
				}
				else trouve=1;
				
				if(trouve==0) return ER_ID_PAS_DECLARE; /*On a rien trouvé*/
				
				token=yylex();
				if(strcmp(u_lex, "(")==0)	// On a détecté une fonction
				{
					int tmp_param=0;
				
					/*p_code*/
					select->deplacement=pCompilation->deplacement;
					int indexInSymbole=chercherSymboleI(tableSymbole, select->nom, select->nomEmplacement);
					char val[5]; sprintf(val, "%d", indexInSymbole);
					char info[128];
					sprintf(info, " #Chargement table des symboles %s => pile: variable %s", val, select->nom);
					addOperation(p_code, "INC", 0, val, info);
					empiler(pCompilation, select->nom, select->valeur, select->typeIdentificateur, select->typeLiteral, select->nomEmplacement);
					/*fin_pcode*/
					
					token=yylex();
					if(strcmp(u_lex, ")")==1)
					{
						jumpInExp=1;
						while(stop==1) //Liste des paramètres
						{
							res=expression(nomEmplacement); /*Chaque paramètre est une expression*/
							tmp_param++;
							if(res!=0) return res;
							
							if(strcmp(u_lex, ",")==0); //On continu
							else stop=0; //On arrête
						}
					}

					if(strcmp(u_lex, ")")==1) return ER_PARENTHESE_FERMANTE; // Lecture de la fin de la parenthèse

					if(tmp_param!=select->nParam) return ER_PARAM_FONCTION;

					struct func *currentFunc=getFunc(sav, select->nom);				
					if(tmp_param!=currentFunc->nReference) return ER_PARAM_FONCTION;
					
					/*p_code*/
					LBA(currentFunc->nReference+1);
					CAL(select->nom);
					STA(currentFunc->nReference+1);

					int nParam=currentFunc->nReference;
					/*Pour chaque paramètre*/
					for(i=nParam-1; i>=0; --i)
					{	/*Si c'est passé par référence*/
						if(currentFunc->reference[i]==1)
						{
							// Cherche le nom de la variable à affecter
							struct element *src=pCompilation->base[pCompilation->deplacement-1];
							int j, pos=-1;
							for(j=0; j<pCompilation->deplacement; ++j)
							{
								if(strcmp(src->nom, pCompilation->base[j]->nom)==0 && pos==-1)
									pos=j;
							}

							/*Il faut que ce soit une variable*/
							if(src->typeIdentificateur>=6 && src->typeIdentificateur<=11)
							/*On fait l'affectation*/
							res=STO(src->nom, src->localisation, pos, src->typeLiteral, src->typeIdentificateur);
							else
								return ER_PARAM_FONCTION;
						}
						else	/*Sinon on supprime l'emplacement mémoire*/
							INC(0);
					}
					/*Fin p_code*/
				}
				else /*C'est un identifiant*/
				{	/*On le charge*/
					LOD(select->nom, select->typeIdentificateur, select->typeLiteral, select->nomEmplacement, select->deplacement);
					jumpInExp=1; 
				}
				
			}
			else /*C'est pas un identifiant*/
			{	/*Cherche son type*/
				if(token==CONST_ENTIERE){ typeI=cst_entier; typeL=t_entier; }
				else if(token==CONST_BOOLEENNE){ typeI=cst_boolean; typeL=t_boolean; }
				else if(token==CONST_CARACTERE){ typeI=cst_char; typeL=t_char; }
				else if(token==CONST_CHAINE){ typeI=cst_string; typeL=t_string; }
				else{ typeI=cst_reel; typeL=t_reel; }
				

				if(strcmp(u_lex, "true")==0) strcpy(val, "1");
				else if(strcmp(u_lex, "false")==0) strcpy(val, "0");
				else 
				{	/*On enlève les '' de la chaine ou du caractère*/
					if(token==CONST_CHAINE || token==CONST_CARACTERE)
					{
						//On enlève les '' de 'hello'
						int i;
						for(i=1; i<strlen(u_lex)-1; ++i) val[i-1]=u_lex[i]; 
						
						val[strlen(u_lex)-2]='\000';
					}
					else /*Si il y a un signe -, on doit lui attribué car analex sépare les -*/
					{
						if(negatif==1)
						{
							negatif=0;
							sprintf(val, "%s%s", "-", u_lex);
						}	
						else
							strcpy(val, u_lex); 
					}
				}
				/*Empile le literal*/
				res=LIT(val, typeI, typeL, nomEmplacement); 
				if(res!=0) return res;
			}

			/*Appel.txt et syntex.postfix*/
			sprintf(buffer, "%s terme() %s\n", space, u_lex); fputs(buffer, appel); 
			sprintf(varPostFix, "%s ", u_lex);
			fputs(varPostFix, postFix); 
			/*Fin*/

		}
		else return ER_ID_ENT_REEL_CHAINE; //Autre chose est une erreur

		if(flagPostFix==1)	/*Flag + écriture postfix*/
		{
			flagPostFix=0;
			fputs(opPostFix, postFix);
			opPostFix[strlen(opPostFix)-1]='\000';
			res=OPR(opPostFix);
			if(res!=0) return res;
		}

		if(jumpInExp==0) token=yylex();

		if(strcmp(u_lex, "*")==0 || strcmp(u_lex, "/")==0) /*Détection des * et /*/
		{
			/*Appel.txt et syntax.postfix*/
			sprintf(buffer, "%s terme() %s\n", space, u_lex); fputs(buffer, appel); 
			flagPostFix=1;			
			sprintf(opPostFix, "%s ", u_lex);
			/*Fin*/

			token=yylex();
		}
		else /*Autre chose nous fait quitter terme()*/
		{
			jumpInExp=1;
			sprintf(buffer, "%s Fterme()\n", space); fputs(buffer, appel); terme_expression_counter--;
			return 0;
		}
	}
}

int expression(char nomEmplacement[128])
{
	/*Déclarations*/
	int res, stop=1, i, depth=0, flagPostFix=0;
	char buffer[124], space[124];
	char opPostFix[56];

        /*Appel de terme() pour le fichier appel.txt*/
        depth=terme_expression_counter; terme_expression_counter++;
	strcpy(space, ""); for(i=0; i<depth; ++i) strcat(space, "  "); sprintf(buffer, "%s Dexpression()\n", space); fputs(buffer, appel);

	/*Début de l'automate*/
	if(jumpInExp==0)
	{
		token=yylex();
		if(token==OPER_ARITHMETIQUE && (strcmp(u_lex, "+")==0 || strcmp(u_lex, "-")==0)); //Un terme peut commencer par un + ou un -
	}
	else jumpInExp=0; 
	
	while(stop==1) 
	{
		//lancement du terme
		res=terme(nomEmplacement); 
		if(res!=0) return res;
		
		// On saute une lecture si jumpInExp==1
		if(jumpInExp==1)
			jumpInExp=0;
		else
			token=yylex();	

		/*Si le flag est à 1, j'écris dans le postfix et je fais une OPR*/
		if(flagPostFix==1)
		{
			sprintf(opPostFix, "%s ", opPostFix);
			flagPostFix=0;
			fputs(opPostFix, postFix);

			opPostFix[strlen(opPostFix)-1]='\000';
			res=OPR(opPostFix);
			if(res!=0) return res;
		}
		
		/*Detection d'un + ou -*/
		if((strcmp(u_lex, "+")==0 || strcmp(u_lex, "-")==0))
		{
			/*Appel.txt et syntax.postfix*/
			sprintf(buffer, "%s expression() %s\n", space, u_lex); fputs(buffer, appel);
			flagPostFix=1;		// Si le flag vaut 1, à la prochaine itération, on génère le pcode
			sprintf(opPostFix, "%s", u_lex);
			/*Fin*/
		
			token=yylex(); //Si il y a un + ou un - à la fin, on boucle
		} /*Autre chose, on arrête*/
		else stop=0;
	}

	sprintf(buffer, "%s Fexpression()\n", space); fputs(buffer, appel); terme_expression_counter--;
	return 0;
}

int instruction(char nomEmplacement[128])
{
	/*Déclarations*/
	int res, stop=1, flag=0, emplacement;
	char buffer[56], nom[128];

	/*Sommes-nous dans une fonction? procédure ou dans le programme global?*/
	if(in_function==1) emplacement=local_fonction;
        else if(in_procedure==1) emplacement=local_procedure;
        else emplacement=global;

   	if(strcmp(u_lex, ";")==0) flag=1; //à cause des ;;;;;

	if(jumpInInstruction==0) token=yylex(); 
	else jumpInInstruction=0;
	
	if(strcmp(u_lex, "begin")==0) //Reconnaissance de begin instruction end
	{
		begin_counter++; 
		for(;;) /*Suite d'instruction*/
		{
			res=instruction(nomEmplacement);
			if(res!=0) return res;
			if(in_function==1) //Si on est dans une 

        		{
                		if(contain_return==1) //Si on a déjà trouvé un return
                		{
                        		return 0;
                		}
        		}

			if(strcmp(u_lex, ";")==0);
			else if(strcmp(u_lex, "end")==0) return 0;
			else return ER_POINT_VIRGULE_END;
		}
	}
	else if(strcmp(u_lex, ";")==0) return flag==0?0:ER_POINT_VIRGULE;
	else if(strcmp(u_lex, "end")==0)
	{
		begin_counter--; 
		return 0;
	}
	else if(strcmp(u_lex, "while")==0) // while condition do instruction
	{
		int saveLine, start;
		char value[56];
	
		/* pcode*/
		start=p_code->size;
		NOP();
		/* fin pcode*/

		res=condition(nomEmplacement);
		if(res!=0) return res;

		if(strcmp(u_lex, "do")==1) return ER_DO;

		/*pcode*/
		SFL();	
		saveLine=p_code->size;
		JPC(0);
		/*Fin pcode*/ 

		res=instruction(nomEmplacement);
		if(res!=0) return res;

		/*pcode*/
		sprintf(value, "%d", p_code->size);
		JMP(start);
		char sLine[5]; sprintf(sLine, "%d", p_code->size);
		strcpy(p_code->codes[saveLine]->value, sLine);
		NOP();
		/*Fin pcode*/

		return 0;

	}
	else if(strcmp(u_lex, "for")==0) // for x:=5 to 10 do
	{
		char op[56], endOfCount[56], value[56];
		int flag=0, isIdent=0;
		struct symbole *selectEndSymbole;

		// Le nom de la variable
		token=yylex();
		if(token!=IDENTIFICATEUR) return ER_ID;

		// Recherche le symbole, si il existe, on l'empile sinon erreur
		struct symbole *s=chercherUnSymbole(tableSymbole, u_lex, emplacement, nomEmplacement);
		if(s==NULL) return ER_ID_PAS_DECLARE;

		// Affectation
		token=yylex();
		if(token!=AFFECTATION || strcmp(u_lex, ":=")==1) return ER_AFFECTATION;
		strcpy(op, u_lex);

		// Initialisation
		token=yylex();
		if(token==CONST_ENTIERE || token==CONST_REELLE) LIT(u_lex, cst_entier, t_entier, nomEmplacement);
		else if(token==IDENTIFICATEUR)
		{
			struct symbole *select=chercherUnSymbole(tableSymbole, u_lex, emplacement, nomEmplacement);
			LOD(select->nom, cst_entier, t_entier, select->nomEmplacement, select->deplacement);
		}
		else return ER_INIT_FOR;
	
		// Affectation x:=init dans la pile
		res=STO(s->nom, s->nomEmplacement, s->deplacement, s->typeLiteral, s->typeIdentificateur);
		if(res!=0) return res;

		token=yylex();
                if(strcmp(u_lex, "to")==0) flag=0;
		else if(strcmp(u_lex, "downto")==0) flag=1;
		else return ER_TO;
		
		/*Lecture de la valeur finale du compteur*/
		
		token=yylex();
		if(token==CONST_ENTIERE || token==CONST_REELLE) 
		{ 
			LIT(u_lex, cst_entier, t_entier, nomEmplacement);
			strcpy(endOfCount, u_lex);
		}
		else if(token==IDENTIFICATEUR) 
		{
			selectEndSymbole=chercherUnSymbole(tableSymbole, u_lex, emplacement, nomEmplacement); 
			isIdent=1;
		}
		else return ER_INIT_FOR;

		token=yylex();
		if(strcmp(u_lex, "do")==1) return ER_DO;

		/*pcode*/
		int start=p_code->size, saveJPC;
		NOP();
		LOD(s->nom, s->typeIdentificateur, s->typeLiteral, s->nomEmplacement, s->deplacement); 

		if(isIdent==0)
			LIT(endOfCount, cst_entier, t_entier, nomEmplacement);
		else
			LOD(selectEndSymbole->nom, cst_entier, t_entier, selectEndSymbole->nomEmplacement, selectEndSymbole->deplacement);

		if(flag==0)
			res=OPR(">");
		else 
			res=OPR("<");
		if(res!=0) return res;
		
		SFL();
		saveJPC=p_code->size;
		JPC(1);
		/*Fin pcode*/

                res=instruction(nomEmplacement);
		if(res!=0) return res;

		/*pcode*/
		LOD(s->nom, s->typeIdentificateur, s->typeLiteral, s->nomEmplacement, s->deplacement);
		LIT("1", cst_entier, t_entier, nomEmplacement);
		
		if(flag==0)
			res=OPR("+");
		else 
			res=OPR("-");

		if(res!=0) return res;

		res=STO(nom, nomEmplacement, s->deplacement, s->typeLiteral, s->typeIdentificateur);
		if(res!=0) return res;

		JMP(start);
		char sLine[5]; sprintf(sLine, "%d", p_code->size);
		strcpy(p_code->codes[saveJPC]->value, sLine);
		NOP();
		/*Fin pcode*/

		return 0;

	}
	else if(strcmp(u_lex, "if")==0)
	{
		int saveLine, contentElse=1;
		char value[56];
		struct pile *tmp=constrPile();

		res=condition(nomEmplacement);
		if(res!=0) return res;
		
		if(strcmp(u_lex, "then")==1) return ER_THEN;

		/*pcode*/
		SFL();	
		saveLine=p_code->size;
		JPC(0);
		/*Fin pcode*/ 
		
		res=instruction(nomEmplacement);

		/*pcode*/
		sprintf(value, "%d", p_code->size);
		empiler(tmp, "Tmp", value, -1, -1, "Instruction if");
		JMP(-1);	
		char sLine[5]; sprintf(sLine, "%d", p_code->size);
		strcpy(p_code->codes[saveLine]->value, sLine);	
		NOP();	
		/*Fin pcode*/

		stop=1; 
		token=yylex();
		while(stop==1)
		{
			if(strcmp(u_lex, "else")==0)
			{
				token=yylex();
				if(strcmp(u_lex, "if")==0)
				{
					res=condition(nomEmplacement);
					if(res!=0) return res;

					/*pcode*/
					SFL();
					saveLine=p_code->size;	
					JPC(0);
					/*Fin pcode*/ 

					if(strcmp(u_lex, "then")==1) return ER_THEN; 
	
					res=instruction(nomEmplacement);
					if(res!=0) return res;			
			
					/*pcode*/
					sprintf(value, "%d", p_code->size);
					JMP(-1);
					empiler(tmp, "Tmp", value, -1, -1, "Instruction if");
					char sLine2[5]; sprintf(sLine2, "%d", p_code->size);
					strcpy(p_code->codes[saveLine]->value, sLine2);
					NOP();
					/*Fin pcode*/

					token==yylex();
				}
				else
				{
					stop=0; 
					jumpInInstruction=1; //Saute le prochain yylex() dans instruction()
				}
			} 
			else
			{
				contentElse=0;
				stop=0; 
				jumpInInstruction=1; //Saute le prochain yylex() dans instruction()
			}
		}

		if(contentElse==1)
		{
		
			res=instruction(nomEmplacement);
			if(res!=0) return res;
		}

		/*pcode*/
		int i, ligne, nopLigne=p_code->size;
		struct element *e;

		for(i=0; i<=tmp->deplacement; ++i)
		{
			e=depiler(tmp);
			sscanf(e->valeur, "%d", &ligne); 
			char sLine[5]; sprintf(sLine, "%d", nopLigne);
			strcpy(p_code->codes[ligne]->value, sLine);
		}
		nettoyerPile(tmp);

		NOP();
		/*Fin pcode*/
		
	
		return 0;
	}
	else if(in_function==1 && strcmp(u_lex, function_name)==0 && contain_return==0)
        { /*Si on est dans une fonction, si l'identificateur est le nom de la fonction et si il n'y a pas de return*/
                //On a détécté un return
                contain_return=1;
		//Recherche le symbole, si il existe,
		struct symbole *s=chercherUnSymbole(tableSymbole, u_lex, emplacement, nomEmplacement);
		if(s==NULL) return ER_ID_PAS_DECLARE;
		
                token=yylex();  //lecture d'un :=
                if(strcmp(u_lex, ":=")==1) return ER_AFFECTATION;

                res=expression(nomEmplacement);
		if(res!=0) return res;
		
		res=STO(s->nom, nomEmplacement, s->deplacement, s->typeLiteral, s->typeIdentificateur);
		if(res!=0) return res;

		return 0;
        }
	else if(token==IDENTIFICATEUR) //C'est le nom de la variable ou de la fonction
	{	
		int e_s=0;
		if(strcmp(u_lex, "write")==0)
			e_s=1;
		else if(strcmp(u_lex, "writeln")==0)
			e_s=2;
		else if(strcmp(u_lex, "read")==0)
			e_s=3;
		else;
		
		strcpy(nom, u_lex); 	// Sauvegarde dans nom
		
		/*syntax.postfix*/
		sprintf(buffer, "\n%s ", u_lex);
		fputs(buffer, postFix); 
	
		token=yylex(); //On attent un := ou une parenthèse
		if(strcmp(u_lex, ":=")==0) 
		{
			struct symbole *select=chercherUnSymbole(tableSymbole, nom, emplacement, nomEmplacement);
			if(select==NULL) return ER_ID_PAS_DECLARE;

			res=expression(nomEmplacement);
			if(res!=0) return res;
			
			select=chercherUnSymbole(tableSymbole, nom, emplacement, nomEmplacement);
			
			res=STO(nom, nomEmplacement, select->deplacement, select->typeLiteral, select->typeIdentificateur); 
			if(res!=0) return res;
			
			if(strcmp(u_lex, ";")==1) return ER_POINT_VIRGULE;
			else return 0;
		}
		else if(strcmp(u_lex, "(")==0)
		{	
			if(e_s!=0)
			{
				res=inputOutput(nomEmplacement, e_s);
				if(res!=0) return res;
			}
			else
			{
				int tmp_param=0;

				// Recherche si la fonction est déclarée
				struct symbole *select=chercherUnSymbole(tableSymbole, nom, local_fonction, nom); 
				
				int execute_function=0, execute_procedure=0;
				if(select==NULL)
				{
					// Sinon Recherche dans la partie procédure
					select=chercherUnSymbole(tableSymbole, nom, local_procedure, nom);
					if(select==NULL) return ER_ID_PAS_DECLARE;
					else execute_procedure=1;
				}
				else execute_function=1;
				
				int indexInSymbole=chercherSymboleI(tableSymbole, select->nom, select->nomEmplacement);
				char val[5]; sprintf(val, "%d", indexInSymbole);
				char info[128];
				sprintf(info, " #Chargement table des symboles %s => pile: variable %s", val, select->nom);
				addOperation(p_code, "INC", 0, val, info);
				empiler(pCompilation, select->nom, select->valeur, select->typeIdentificateur, select->typeLiteral, select->nomEmplacement);
				token=yylex();
				if(strcmp(u_lex, ")")==1)
				{
					jumpInExp=1;
					while(stop==1) //Liste des paramètres
					{
						res=expression(nomEmplacement);
						tmp_param++;
						if(res!=0) return res;

						if(strcmp(u_lex, ",")==0); //On continu
						else stop=0; //On arrête
					}
				}

				if(strcmp(u_lex, ")")==1) return ER_PARENTHESE_FERMANTE; // Lecture de la fin de la parenthèse
			
				struct func *currentFunc=getFunc(sav, select->nom);		
				if(tmp_param!=currentFunc->nReference) return ER_PARAM_FONCTION;
				
				/*p_code*/
				LBA(currentFunc->nReference+1);
				CAL(nom);
				STA(currentFunc->nReference+1);

				int nParam=currentFunc->nReference;
				int i;
				
				for(i=nParam-1; i>=0; --i)
				{
					if(currentFunc->reference[i]==1)
					{
						// Cherche le nom de la variable à affecter
						struct element *src=pCompilation->base[pCompilation->deplacement-1];
						int j, pos=-1;
						for(j=0; j<pCompilation->deplacement-nParam; ++j)
						{
							if(strcmp(src->nom, pCompilation->base[j]->nom)==0 && pos==-1)
								pos=j;
						}
						
						/*Il faut que ce soit une variable*/
						if(src->typeIdentificateur>=6 && src->typeIdentificateur<=11)
						/*On fait l'affectation*/
						res=STO(src->nom, src->localisation, pos, src->typeLiteral, src->typeIdentificateur);
						else
							return ER_PARAM_FONCTION;
					}
					else
						INC(0);
				}
				
				/*Dépile la variable fonction ou procédure*/
				INC(0);
				/*fin p_code*/
			}
			
			token=yylex();	
			if(strcmp(u_lex, ";")==1) return ER_POINT_VIRGULE;
			else return 0;
		}
		else return ER_AFFECTATION_OR_FONCTION;
	}
}

int constante(char nomEmplacement[128])
{
	/*
		Automate:
		const
			un=1;
			message='salut';
	*/

	/*Déclarations*/
	int stop=1, res, typeI, typeL, emplacement;
	struct liste *error, *tmp=constrListe();
	char nom[128], valeur[128];

	token=yylex();
	if(token!=IDENTIFICATEUR) return ER_IDENTIFICATEUR; //Lecture d'un identificateur
	
	if(in_function==1) emplacement=local_fonction;
        else if(in_procedure==1) emplacement=local_procedure;
        else emplacement=global;
	
	while(stop==1)
	{
		strcpy(nom, u_lex);
		token=yylex();	//Lecture d'une affectation
		if(strcmp(u_lex, "=")==1) return ER_EGUAL;	

		token=yylex(); //Lecture d'un entier, d'un caractère ou d'une chaine ou d'une reel
		strcpy(valeur, u_lex);
 		
		/*Test chaque type de la constante*/
		if(token==CONST_ENTIERE){ typeI=cst_entier; typeL=t_entier; }
		else if (token==CONST_CARACTERE){ typeI=cst_char; typeL=t_char; }
		else if (token==CONST_CHAINE){ typeI=cst_string; typeL=t_string; }
		else if (token==CONST_BOOLEENNE)
		{ 
			typeI=cst_boolean; typeL=t_boolean; 
			if(strcmp(valeur, "true")==0) strcpy(valeur, "1");
			else strcpy(valeur, "0");
		}
		else if (token==CONST_REELLE){ typeI=cst_reel; typeL=t_reel; }
		else return ER_ENT_REEL_CHAINE_CAR;

		// On l'ajoute à la table des symbôles
		ajouterSymbole(tmp, nom, typeI, typeL, valeur, emplacement, -1, nomEmplacement, 0, passage_aucun);
	
		token=yylex(); //Suivit d'un ;
		if(strcmp(u_lex, ";")==1) return ER_POINT_VIRGULE;

		token=yylex(); //Lecture de la prochaine instruction, si c'est ni var ou begin, on boucle
		if(strcmp(u_lex, "begin")==0 || strcmp(u_lex, "procedure")==0 || strcmp(u_lex, "function")==0 || strcmp(u_lex, "var")==0)
		{
			stop=0;
			error=ajouterListeSymbole(tableSymbole, tmp);
			if(error!=NULL)
			{
				printSymbole(error);
				nettoyerListe(error);
				nettoyerListe(tmp);
				return ER_ID_DEJA_DECLARE;
			}

			// Ajoute les variables dans la pile
			if(strcmp(nomEmplacement, "Main")==1)
			{
				struct symbole *courant=tmp->tete;
				while(courant!=NULL)
				{
					int pos=chercherSymboleI(tableSymbole, courant->nom, "Main");
					char val[5]; 
					sprintf(val, "%d", pos);
					empiler(pCompilation, courant->nom, courant->valeur, courant->typeIdentificateur, courant->typeLiteral, courant->nomEmplacement);
					char info[128];
					sprintf(info, " #Chargement table des symboles %s => pile: variable %s", val, courant->nom);
					addOperation(p_code, "INC", 0, val, info);				
					courant=courant->suivant;
				}
			}

			nettoyerListe(error);
			nettoyerListe(tmp);
			
		}
		else
		{
			if(token!=IDENTIFICATEUR) return ER_ID;
			strcpy(nom, u_lex);
		}
	}

	return 0;
}

int variable(char nomEmplacement[128])
{
	/*
		Automate:
		var
		
		i,j:integer;
		bool:boolean;
		x:char;
	*/
	
	/*Déclarations*/
	int res, stop2=1, emplacement;
	char buffer[512];
	struct liste *error, *tmp=constrListe();

	if(in_function==1) emplacement=local_fonction;
        else if(in_procedure==1) emplacement=local_procedure;
        else emplacement=global;	
	
	for(;;) //Suite de déclaration
	{
		token=yylex(); //Lis un identifiant
       		if(token!=IDENTIFICATEUR) return ER_IDENTIFICATEUR;	//Si ce n'est pas un identifiant, alors c'est une erreur
		else if(strcmp(u_lex, "begin")==0 || strcmp(u_lex, "const")==0 || strcmp(u_lex, "procedure")==0 || strcmp(u_lex, "function")==0) 
		//L'un des mots clefs nous fait quitter la fonction
		{
			return 0;
		}
		else;
	
		while(stop2==1) //boucle pour chaque identificateur: ident, ident
		{
			ajouterSimpleSymbole(tmp, u_lex, "Aucune", emplacement, nomEmplacement, 0, passage_aucun); 
			token=yylex(); //détection de la virgule
			if(strcmp(u_lex, ",")==1) stop2=0;
			else 
			{
				//Il y a une virgule, on regarde si le prochain est un identificateur
				token=yylex();
				if(token!=IDENTIFICATEUR) return ER_IDENTIFICATEUR;
			}
		}
		stop2=1;
		
		if(strcmp(u_lex, ":")==1) return ER_DOUBLE_POINT; //Reconnaissance du :

		token=yylex();	//Du type ...
		if(token==IDENTIFICATEUR)
		{
			if(strcmp(u_lex, "integer")==0) appliquerType(tmp, var_entier, t_entier, 0);
			else if(strcmp(u_lex, "real")==0) appliquerType(tmp, var_reel, t_reel, 0);
			else if(strcmp(u_lex, "char")==0) appliquerType(tmp, var_char, t_char, 0);
			else if(strcmp(u_lex, "string")==0) appliquerType(tmp, var_string, t_string, 0);
			else if(strcmp(u_lex, "boolean")==0) appliquerType(tmp, var_boolean, t_boolean, 0);
			else if(strcmp(u_lex, "byte")==0) appliquerType(tmp, var_byte, t_byte, 0);
			else return ER_TYPE;
		}
		else return ER_TYPE;
		
		error=ajouterListeSymbole(tableSymbole, tmp);
		if(error!=NULL)
		{
			printSymbole(error);
			nettoyerListe(error);
			nettoyerListe(tmp);
			return ER_ID_DEJA_DECLARE; 
		}
		
		// Ajoute les variables dans la pile
		if(strcmp(nomEmplacement, "Main")==1)
		{
			struct symbole *courant=tmp->tete;
			while(courant!=NULL)
			{
				int pos=chercherSymboleI(tableSymbole, courant->nom, courant->nomEmplacement);
				char val[5]; 
				sprintf(val, "%d", pos);
				empiler(pCompilation, courant->nom, courant->valeur, courant->typeIdentificateur, courant->typeLiteral, courant->nomEmplacement);
				char info[128];
				sprintf(info, " #Chargement table des symboles %s => pile: variable %s", val, courant->nom);
				addOperation(p_code, "INC", 0, val, info);				
				courant=courant->suivant;
			}
		}

		nettoyerListe(error); 
		nettoyerListe(tmp); 
		
		token=yylex();	//Du ;
		if(strcmp(u_lex, ";")==1) return ER_POINT_VIRGULE; 
		if(strcmp(nomEmplacement, "Main")==0) nettoyerPile(pCompilation);
	}
}

int fonction()
{
	nettoyerPile(pCompilation);
	int res, nParam=0, i;

        /*Déclaration des variables*/
        int stop=1, stop2=1, error=0, passage=0;
	struct liste *errorSymbole=NULL, *tmp=constrListe(), *func_ret=constrListe();
	char nom[128], valeur[128];
	int param[100];

        /*Ajout à la table des symbôles le nom de la fonction*/
        token=yylex();                                          // identificateur de la fonction
	strcpy(function_name, u_lex);				// Mémorisation du nom de la fonction => utilisation du return
	ajouterSimpleSymbole(func_ret, function_name, "aucune", local_fonction, function_name, 0, passage_aucun);
	NOP();
	errorSymbole=ajouterListeSymbole(tableSymbole, func_ret);
	if(errorSymbole!=NULL)
	{
		printSymbole(errorSymbole);
		nettoyerListe(errorSymbole);
		nettoyerListe(tmp);
		return ER_ID_DEJA_DECLARE;
	}
	
	// Mémorisation du symbole pour appliquer le type (lu à la fin de la fonction avant le ;
	struct symbole *symFunction=chercherUnSymbole(tableSymbole, function_name, local_fonction, function_name);
	nettoyerListe(func_ret);
	/*Fin*/

        if(token!=IDENTIFICATEUR) return ER_IDENTIFICATEUR;

        token=yylex();
        if(token!=SEPARATEUR || strcmp(u_lex, "(")==1) return ER_PARENTHESE_OUVRANTE; //Paramètres ... parenthèse ouvrante

	token=yylex();
        while(stop==1) //Liste des paramètres
        {
		stop2=1; passage=0;
		if(strcmp(u_lex, ")")==0){stop=0; stop2=0; }
		if(strcmp(u_lex, "var")==0){ token=yylex(); passage=1; }// On a une déclaration de variable
				
		while(stop2==1)
		{
			if(token!=IDENTIFICATEUR) return ER_IDENTIFICATEUR;

			if(passage==1)
			{
				ajouterSimpleSymbole(tmp, u_lex, "aucune", local_fonction, function_name, 0, passage_reference);
				param[nParam]=1;
			}
			else
			{
				param[nParam]=0;
				ajouterSimpleSymbole(tmp, u_lex, "aucune", local_fonction, function_name, 0, passage_copie);	
			}		

			nParam++;

			token=yylex();	//Lecture soit d'une ,
			if(strcmp(u_lex, ",")==0) token=yylex(); //On boucle
			else stop2=0; //On arrête
		}	

		if(stop==1)
		{
			if(strcmp(u_lex, ":")==1) return ER_PARAM_FONCTION;

			token=yylex();	// Lecture d'un type
			if(token!=IDENTIFICATEUR) return ER_TYPE;

			if(strcmp(u_lex, "integer")==0) appliquerType(tmp, var_entier, t_entier, 0);
			else if(strcmp(u_lex, "real")==0) appliquerType(tmp, var_reel, t_reel, 0);
			else if(strcmp(u_lex, "char")==0) appliquerType(tmp, var_char, t_char, 0);
			else if(strcmp(u_lex, "string")==0) appliquerType(tmp, var_string, t_string, 0);
			else if(strcmp(u_lex, "boolean")==0) appliquerType(tmp, var_boolean, t_boolean, 0);
			else if(strcmp(u_lex, "byte")==0) appliquerType(tmp, var_byte, t_byte, 0);
			else return ER_TYPE;
			
			errorSymbole=ajouterListeSymbole(tableSymbole, tmp);
			if(errorSymbole!=NULL)
			{
				printSymbole(errorSymbole);
				nettoyerListe(errorSymbole);
				nettoyerListe(tmp);
				return ER_ID_DEJA_DECLARE;
			}

			nettoyerListe(errorSymbole);
			nettoyerListe(tmp);

			token=yylex();	
			if(strcmp(u_lex, ";")==0) token=yylex(); //On continu
			else stop=0; //On arrête
		}
        }

	if(errorSymbole!=NULL)
	nettoyerListe(errorSymbole);
	nettoyerListe(tmp);

	if(strcmp(u_lex, ")")==1) return ER_PARENTHESE_FERMANTE; // Lecture de la fin de la parenthèse

	// Lecture du type de retour de la fonction
	token=yylex();
	if(token!=AFFECTATION || strcmp(u_lex, ":")==1) return ER_TYPE_FONCTION;

	token=yylex();
	if(strcmp(u_lex, "integer")==0){ symFunction->typeIdentificateur=var_entier; symFunction->typeLiteral=t_entier; symFunction->nParam=nParam; }
	else if(strcmp(u_lex, "real")==0){ symFunction->typeIdentificateur=var_reel; symFunction->typeLiteral=t_reel; symFunction->nParam=nParam; }
	else if(strcmp(u_lex, "char")==0){ symFunction->typeIdentificateur=var_char; symFunction->typeLiteral=t_char; symFunction->nParam=nParam; }
	else if(strcmp(u_lex, "string")==0){ symFunction->typeIdentificateur=var_string; symFunction->typeLiteral=t_string; symFunction->nParam=nParam; }
	else if(strcmp(u_lex, "boolean")==0){ symFunction->typeIdentificateur=var_boolean; symFunction->typeLiteral=t_boolean; symFunction->nParam=nParam; }
	else if(strcmp(u_lex, "byte")==0){ symFunction->typeIdentificateur=var_byte; symFunction->typeLiteral=t_byte; symFunction->nParam=nParam; }
	else return ER_TYPE_FONCTION;

	token=yylex();
        if(token!=SEPARATEUR || strcmp(u_lex, ";")==1) return ER_POINT_VIRGULE; // Le ;
	
	loadSymboleIntoListe(tableSymbole, pCompilation, function_name, p_code, 0);

	/*p_code*/
	addFunc(sav, function_name, p_code->size);
	addParam(sav, function_name, param, nParam);
	/*fin p_code*/

      	res=bloc(function_name); //On traite le corps de la procédure
	if(res!=0) return res;

	int size=pCompilation->deplacement;
	for(i=0; i<(size-(nParam+1)); ++i)
		INC(0); 

	for(i=0; i<=nParam; ++i)
		INC(1); 

	/*p_code*/
	RET(valeur);
	/*fin p_code*/

	return 0;
}

int procedure()
{	
	nettoyerPile(pCompilation);

	/*Déclaration des variables*/
	int res, nParam=0, i, passage=0;
        int stop=1, stop2=1, error=0;
	struct liste *errorSymbole=NULL, *tmp=constrListe(), *func_ret=constrListe();
	char nom[128], valeur[128], procedure_name[128];
	int param[100];

        /*Analyse de l'entête*/
        token=yylex();						//identificateur de la procédure
	strcpy(procedure_name, u_lex);
	ajouterSimpleSymbole(func_ret, procedure_name, "aucune", local_procedure, procedure_name, nParam, passage_aucun);
	NOP();
	errorSymbole=ajouterListeSymbole(tableSymbole, func_ret);
	if(errorSymbole!=NULL)
	{
		printSymbole(errorSymbole);
		nettoyerListe(errorSymbole);
		nettoyerListe(tmp);
		return ER_ID_DEJA_DECLARE;
	}
	nettoyerListe(func_ret);


        if(token!=IDENTIFICATEUR) return ER_IDENTIFICATEUR;

        token=yylex();
        if(token!=SEPARATEUR || strcmp(u_lex, "(")==1) return ER_PARENTHESE_OUVRANTE; //Paramètres ... parenthèse ouvrante

	token=yylex();
        while(stop==1) //Liste des paramètres
        {
		stop2=1; passage=0;

		if(strcmp(u_lex, ")")==0){ stop=0; stop2=0; }
                
                if(strcmp(u_lex, "var")==0){ token=yylex(); passage=1; }// On a une déclaration de variable

                while(stop2==1)
                {
                        if(token!=IDENTIFICATEUR) return ER_IDENTIFICATEUR;

			if(passage==1)
			{
				ajouterSimpleSymbole(tmp, u_lex, "aucune", local_procedure, procedure_name, 0, passage_reference);
				param[nParam]=1;	
			}
			else	
			{
				param[nParam]=0;
				ajouterSimpleSymbole(tmp, u_lex, "aucune", local_procedure, procedure_name, 0, passage_copie);
			}

			nParam++;
                        token=yylex();  //Lecture soit d'une ,
                        if(strcmp(u_lex, ",")==0) token=yylex(); //On boucle
                        else stop2=0; //On arrête
                }

                if(strcmp(u_lex, ":")==1) return ER_PARAM_FONCTION;

                if(stop==1)
		{
			token=yylex();  // Lecture d'un type
		        if(strcmp(u_lex, "integer")==0) appliquerType(tmp, var_entier, t_entier, 0);
			else if(strcmp(u_lex, "real")==0) appliquerType(tmp, var_reel, t_reel, 0);
			else if(strcmp(u_lex, "char")==0) appliquerType(tmp, var_char, t_char, 0);
			else if(strcmp(u_lex, "string")==0) appliquerType(tmp, var_string, t_string, 0);
			else if(strcmp(u_lex, "boolean")==0) appliquerType(tmp, var_boolean, t_boolean, 0);
			else if(strcmp(u_lex, "byte")==0) appliquerType(tmp, var_byte, t_byte, 0);
			else return ER_TYPE;

			errorSymbole=ajouterListeSymbole(tableSymbole, tmp); 
			if(errorSymbole!=NULL)
			{
				printSymbole(errorSymbole);
				nettoyerListe(errorSymbole);
				nettoyerListe(tmp);
				return ER_ID_DEJA_DECLARE;
			}

			nettoyerListe(errorSymbole);
			nettoyerListe(tmp);

		        token=yylex();
		        if(strcmp(u_lex, ";")==0) token=yylex(); //On continu
		        else stop=0; //On arrête
		}
        }

	if(errorSymbole!=NULL)
	nettoyerListe(errorSymbole);
	nettoyerListe(tmp);

        if(strcmp(u_lex, ")")==1) return ER_PARENTHESE_FERMANTE; // Lecture de la fin de la parenthèse
	
	token=yylex();
        if(token!=SEPARATEUR || strcmp(u_lex, ";")==1) return ER_POINT_VIRGULE; // Le ;

	/*p_code*/
	addFunc(sav, procedure_name, p_code->size);
	addParam(sav, procedure_name, param, nParam);
	/*fin p_code*/

	loadSymboleIntoListe(tableSymbole, pCompilation, procedure_name, p_code, 0);

	res=bloc(procedure_name); //On traite le corps de la procédure
	if(res!=0) return res;

	int size=pCompilation->deplacement;
	for(i=0; i<(size-(nParam+1)); ++i)
		INC(0); 
	for(i=0; i<=nParam; ++i)
		INC(1); 

	/*p_code*/
	RET(valeur);
	/*fin p_code*/

	return 0;
}

int bloc(char nomEmplacement[128])
{
	/*Déclarations des variables*/
	int var=0, cons=0, stop=0, stop2=0, i, res;	//Flag pour nous informer si le bloc variable a déjà été lu, idem pour le bloc des constantes
	token=yylex();
	while(stop==0)
	{
		if(strcmp(u_lex, "var")==0)
		{
			if(var==1) return ER_BLOC_VARIABLE_DECLARE;
			var=1;

                        res=variable(nomEmplacement); //Analyse la variable
                        if(res!=0) return res;
		}
		else if(strcmp(u_lex, "const")==0)
		{
			if(cons==1) return ER_BLOC_CONSTANTE_DECLARE;
                        cons=1;

                        res=constante(nomEmplacement); //Analyse la variable
                        if(res!=0) return res;
		}
		else if(strcmp(u_lex, "function")==0 && in_function==0 && in_procedure==0)
		{	
			contain_return=0;		//Initialise le boolean
			in_function=1;			//Flag nous indiquant qu'on est dans une fonction
				res=fonction(nomEmplacement);
				if(res!=0) return res;

				if(contain_return==0) return ER_MANQUE_RETURN;
				
				token=yylex();
			in_function=0;	//On sort de la fonction
		}
		else if(strcmp(u_lex, "procedure")==0 && in_function==0 && in_procedure==0) //On a le droit d'entré si on est pas dans une fonction, ni dans une procédure
		{
			in_procedure=1;
				res=procedure(nomEmplacement);
				if(res!=0) return res;

				token=yylex();
			in_procedure=0;
		}
		else if(strcmp(u_lex, "begin")==0) stop=1;
		else return ER_DECLARATION;
	}
	
	/*p_code début du main*/
	if(strcmp(nomEmplacement, "Main")==0) MAI();
	/*Fin p_code*/

	if(strcmp(nomEmplacement, "Main")==0) loadSymboleIntoListe(tableSymbole, pCompilation, "Main", p_code, 1);
	begin_counter=0;
	begin_counter++;
        for(;;)  //Suite d'instruction
        {
		res=instruction(nomEmplacement);
		
               	if(res!=0) return res;
		
               	if(strcmp(u_lex, ";")==0);
                else if(strcmp(u_lex, "end")==0)
                {
			if(begin_counter==0) //Signalement que c'est le end de fin
                        {
				token=yylex();
				if(in_function==1 || in_procedure==1)	//Dans une fonction/procédure, on a un end; 
				{
					if(strcmp(u_lex, ";")==0) return 0;
                                        else return ER_POINT;
				}
				else	//Sinon on a un end.
				{
                                	if(strcmp(u_lex, ".")==0) //Suivit du .
                               		{
						NOP();
						token=yylex();  //Si il y a du code encore derrière
                                       		if(token!=0)
                                              		return ER_CODE_APRES_POINT; //erreur
                                       		else return 0; //COde correct
                                	}
                                	else return ER_POINT;
				}
                        }
                 }
	}
}

int header()
{
	/*
		L'automate:
		program ident(ident, ident);
	*/

	/*Déclaration des variables*/
	int stop=1, error=0;

	/*Analyse de l'entête*/
	token=yylex();
	if(token==IDENTIFICATEUR && strcmp(u_lex, "program")==0)
	{
		token=yylex();
		if(token!=IDENTIFICATEUR) return ER_IDENTIFICATEUR;

		token=yylex();
                if(token!=SEPARATEUR || strcmp(u_lex, "(")==1) return ER_PARENTHESE_OUVRANTE;
		while(stop==1)
		{
			token=yylex();
		
			if(token==IDENTIFICATEUR);
              	 	else if(token==SEPARATEUR && strcmp(u_lex, ")")==0) stop=0;
               		else return ER_PARAM_FONCTION;

			if(stop==1) //Si je ne dois pas m'arrêter	
			{
				token=yylex();			//Lecture d'un séparateur
				if(token!=SEPARATEUR) return ER_SEPARATEUR;
				else
				{
					if(strcmp(u_lex, ")")==0) stop=0;
					else if(strcmp(u_lex, ",")==0);
					else return ER_PARENTHESE_FERMANTE_VIRGULE;
				}
			}
		}	
		
		token=yylex();
		if(token!=SEPARATEUR || strcmp(u_lex, ";")==1)
		return ER_POINT_VIRGULE;

		/*Analyse de la partie bloc*/
		return bloc("Main");
	}	
	else return ER_PROGRAM;
}

int program()
{
	/*Quelque initialisation*/
	begin_counter=0;								
	terme_expression_counter=0;				
	in_function=0;					
	in_procedure=0;					
	contain_return=0;					
	jumpInExp=0;	
	jumpInInstruction=0;

	int ret=header();
	return ret;
}
